﻿<%@ WebHandler Language="C#" Class="GIMUploaderReceiver" %>

using System;
using System.Web;
using System.IO;
using System.Text;
using GIMUploaderCommon;
using System.Threading;

public class GIMUploaderReceiver : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        //如果客户端请求已经失去连接，不再处理提交的数据，避免数据写入错误。
        if (!context.Response.IsClientConnected) { return; }
        
        //获取操作命令和文件标示
        string cmd = context.Request.Headers[Config.CmdHeader];
        string guid = context.Request.Headers[Config.GUIDHeader];
        
        //获取保存路径并根据guid生成文件名{
        string path = System.Configuration.ConfigurationManager.AppSettings["GIMUploaderFilePath"];
        if (path != null)
        {
            Config.Path = System.Configuration.ConfigurationManager.AppSettings["GIMUploaderFilePath"];
        } 
        if (!Directory.Exists(Config.Path))
        {
            Directory.CreateDirectory(Config.Path);
        } 
        string file = Config.Path + guid + ".tmp";
        //}
        
        
        switch (cmd)
        {
            //hello，查询上传进度
            case Config.CMD_Hello:
                DoHelloProcess(context, file);
                break;

            case Config.CMD_Query:
                DoQueryProcess(context, file);
                break;

            //保存数据
            case Config.CMD_UploadData:
                DoUploadData(context, file);
                break;

            default:
                break;
        }
        context.Response.Expires = -1;
        context.Response.Write("服务新干线大文件上传数据接收程序！");
    }

    private void DoHelloProcess(HttpContext context, string file)
    {
        try
        {
            if (!File.Exists(file))
            {
                FileStream fs = File.Create(file);
                fs.Close();                
            }
            FileInfo fi = new FileInfo(file); 
            context.Response.AddHeader(Config.ReturnHeader, Config.Return_OK);
            context.Response.AddHeader(Config.GIMUploadStartHeader, fi.Length.ToString());


        }
        catch (Exception e)
        {
            WriteLog(e.Message + "\r\n" + e.StackTrace);
            context.Response.AddHeader(Config.ReturnHeader, Config.Return_ERROR);
             throw;
        }
        
    }

    private void DoQueryProcess(HttpContext context, string file)
    {
        long startIndex = 0;
        try
        {
            if (File.Exists(file))
            {
                FileInfo fi = new FileInfo(file);
                context.Response.AddHeader(Config.ReturnHeader, Config.Return_OK);
                startIndex = fi.Length;
            }  
        }
        catch (Exception e)
        {
            WriteLog(e.Message + "\r\n" + e.StackTrace);
            context.Response.AddHeader(Config.ReturnHeader, Config.Return_ERROR);
            throw;
        }
        context.Response.AddHeader(Config.GIMUploadStartHeader, startIndex.ToString());
    }

    private void DoUploadData(HttpContext context, string file)
    {  
        //取出上传的数据
        int length =Convert.ToInt32(context.Request.InputStream.Length);
        byte[] content = new byte[length];
        context.Request.InputStream.Read(content,0,length); 
        
        //获取md5，并和已经上传的数据的md5进行对比
        string srcMD5 = context.Request.Headers[Config.MD5Header];
        string md5 = CommonHelper.GetDataMD5(content);
        if (srcMD5 != md5) 
        {
            context.Response.AddHeader(Config.ReturnHeader, Config.Return_ERROR);
            return;
        }
        
        //读取当前提交过来的块索引
        int BlockNubmer = Convert.ToInt32(context.Request.Headers[Config.BlockNumberHeader]);
        //根据数据包索引，保存到相应位置。
        FileStream fs = File.OpenWrite(file);
        try
        {
            fs.Seek(BlockNubmer * Config.BufferSize, SeekOrigin.Begin);
            fs.Write(content, 0, length);
            fs.Close();
            context.Response.AddHeader(Config.ReturnHeader, Config.Return_OK);
        }
        catch (Exception e)
        {
            WriteLog(e.Message + "\r\n" + e.StackTrace);
            context.Response.AddHeader(Config.ReturnHeader, Config.Return_ERROR);
        }
        finally {
            fs.Close();
        }

    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }

    private void WriteLog(string str) {
        string file = HttpContext.Current.Server.MapPath("/");
        file = Path.Combine(file, string.Format("{0}.log", DateTime.Now.ToString("yyyMMdd")));
        FileStream fs;
        if (!File.Exists(file))
        {
            fs = File.Create(file);
        }
        else
        {
            fs = File.OpenWrite(file);
            fs.Seek(0, SeekOrigin.End);
        }
        
        str = string.Format("{0}   {1}\r\n", DateTime.Now.ToString(),str);
        Encoding text = Encoding.Default;
        text.GetBytes(str);
        fs.Write(text.GetBytes(str),0,str.Length);
        fs.Close();
        
    }

}